package pokerAI.PokerAI;

import java.io.IOException;
import java.util.LinkedList;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;
import android.widget.Toast;
import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
public class GameState extends Activity {
        private LinkedList<Player> players;
        private int maxPlayers;
       
        private Deck myDeck;
        private Player currPlayer;
        private Player dealer;
        private LinkedList<Card> communityCards;
        private Player better;
        private int pot;
        private int currBet;
        private boolean handOver;
        private int currRound; //0 = preflop, 1 = flop, 2 = river, 3 = turn
        private int pCount;
        private int foldCount;
        private LinkedList<Action> actionLog;
        private int handCount;

        
        //UI Widgets
    	private Button UserButtonFold;
    	private Button UserButtonCall;
    	private Button UserButtonRaise;
    	private Button UserButtonLower;
    	
    	//UI Cards
    	private ImageView BoardFlop1;
    	private ImageView BoardFlop2;
    	private ImageView BoardFlop3;
    	private ImageView BoardTurn;
    	private ImageView BoardRiver;
    	private TextView BoardPot;
    	
    	//Player UI
    	private ImageView PlayerCard1;
    	private ImageView PlayerCard2;
    	private TextView PlayerStatus;
    	private TextView PlayerMoney;
    	
    	public GameState() {
    		//Super Class
    		super();
    		
            //Init Local Variables
            maxPlayers = 5;
            players = new LinkedList<Player>();
            communityCards = new LinkedList<Card>();        
            myDeck = new Deck();
            handOver = false;
            foldCount = 0;
            pCount = 0;
            actionLog = new LinkedList<Action>();
            handCount = 0;

            
            //Add Players
            addPlayer(new AIPlayer("AI: Snookie", 0, this));
            addPlayer(new AIPlayer("AI: Ronni", 1, this));
            addPlayer(new AIPlayer("AI: Pauli", 2, this));
            addPlayer(new AIPlayer("AI: Barack", 3, this));
            initAIPlayers();
            //addPlayer(new Player("Human", 5));
    		
    	}
    	
               
        /** Called when the activity is first created. */
        @Override
        public void onCreate(Bundle savedInstanceState) {
           
            
        	//Set Content View from mainGameTable.xml
            super.onCreate(savedInstanceState);
            setContentView(R.layout.maingametable);
            
    		// Get UI Button View ID's
        	this.UserButtonFold = (Button) findViewById(R.id.UserButtonFold);
        	this.UserButtonCall = (Button) findViewById(R.id.UserButtonCall);
            this.UserButtonRaise = (Button) findViewById(R.id.UserButtonRaise); 
            this.UserButtonLower = (Button) findViewById(R.id.UserButtonLower);
            
            //Get UI Card View ID's
        	this.BoardFlop1 = (ImageView) findViewById(R.id.BoardFlop1);
        	this.BoardFlop2 = (ImageView) findViewById(R.id.BoardFlop2);
            this.BoardFlop3 = (ImageView) findViewById(R.id.BoardFlop3); 
            this.BoardTurn = (ImageView) findViewById(R.id.BoardTurn);
            this.BoardRiver = (ImageView) findViewById(R.id.BoardRiver);
            this.BoardPot = (TextView) findViewById(R.id.BoardPot);
            
            //Get UI Player View ID's
            for (int i = 0; i < 4; i++) {
            	players.get(i).setPlayerCard1(	(ImageView) findViewById(players.get(i).card1Id));
                players.get(i).setPlayerCard2(	(ImageView) findViewById(players.get(i).card2Id));
                players.get(i).setPlayerStatus(	(TextView) findViewById(players.get(i).statusId));
                players.get(i).setPlayerMoney(	(TextView) findViewById(players.get(i).moneyId));
                players.get(i).setPlayerRole(	(ImageView) findViewById(players.get(i).roleId));
            }
            
            /* User Control: Event Handlers */
            //Fold
            /*
            this.UserButtonFold.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                	
               	 Toast.makeText(getBaseContext(), "Welcome to the Shore", 
                  		Toast.LENGTH_SHORT).show();
                  		
                  		                if(action == "bet") {
                        bet();
                }
                if(action == "raise"){
                        raise();
                }
                if(action == "fold")
                        fold();
                if(action == "check")
                        check();
                if(action == "call")
                        call();
                	
                	 
                	 
                }
            }); 
            */
            //Call
            this.UserButtonCall.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                	
                	//currentBet = lastCurrBet;
                	//this.call();
       			  
                }
            }); 
            
            //Raise
            this.UserButtonRaise.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                	
                	//Set 'UserButtonLower' to visible (invisible = 4)
                	UserButtonLower.setVisibility(0);
               	 Toast.makeText(getBaseContext(), "Welcome to the Shore", 
                  		Toast.LENGTH_SHORT).show();
               	 
               	 //this.raise();
                 
                	 
                	 
                }
            }); 
            
            //Lower
            this.UserButtonLower.setOnClickListener(new View.OnClickListener() {
                public void onClick(View v) {
                	
               	 Toast.makeText(getBaseContext(), "Welcome to the Shore", 
                  		Toast.LENGTH_SHORT).show();
                	 
                }
            }); 
            

            
            //Game State
            
            try {
				this.playGame();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
            
        }
        
        private void initAIPlayers()
        {
                
                for(int i=0; i<this.players.size(); i++)
                {
                        if(this.players.get(i).getType() == "AI")
                        {
                                ((AIPlayer) players.get(i)).init();
                        }
                }
        }

        
        //@summary: Keep Game Looping
        public void playGame() throws IOException
        {
        	//Initialize Game
        	this.initHand();
        	this.initRound();
        	boolean flag = this.playRound();
  
            //Loop
             if(flag)
             {
            	 //gameRunner.nextRound()
                 for(int i=0; i<this.players.size(); i++)
                 {
                         if(this.players.get(i).getType() == "AI")
                         {
                                 ((AIPlayer) this.players.get(i)).resetRound();
                         }
                 }
                 this.incrementRound();
                 this.initRound();
             }
             else
             {
            	 //gameRunner.nextHand()
                 this.initHand();
             } 
             
        }
       
        public void addPlayer(Player p)
        {
                pCount++;
                if(players.size() < maxPlayers)
                        players.add(p);
        }
        public void addToPot(int toAdd)
        {
                pot += toAdd;
                updatePot(toAdd);
        }
        


		public void dealCard()
        {
                int currPlayerIndex = players.indexOf(currPlayer);
                do
                {
                        currPlayer.receiveCard(myDeck.getNextCard());
                        currPlayer = getNextPlayer(currPlayer);
                }
                while(players.indexOf(currPlayer) != currPlayerIndex);  
        }



		public void dealFlop(){
                // flop is placed on the table, but burn one first
                myDeck.getNextCard();
                communityCards.add(myDeck.getNextCard());
                communityCards.add(myDeck.getNextCard());
                communityCards.add(myDeck.getNextCard());
                printFlop();
        }
        public void dealRiver(){
                // river is placed on table, but burn first
                myDeck.getNextCard();
                communityCards.add(myDeck.getNextCard());
                printRiver();
        }
        public void dealTurn(){
                // turn is placed on table, but burn one first
                myDeck.getNextCard();
                communityCards.add(myDeck.getNextCard());
                printTurn();
        }
        private void fold()
        {
                currPlayer.fold();
                foldCount++;    /////////////// vincent make sure fold count goes up first bc get next player needs that info
                currPlayer = getNextPlayer(currPlayer);
        }
       
        public int getCurrBet()
        {
                return currBet;
        }
        public Player getCurrentPlayer(){
                return currPlayer;
        }
        private Player getNextPlayer(Player p)
        {
                int currPlayerIndex = players.indexOf(currPlayer);
                Player toReturn;
                System.out.println("pCount is: " + pCount + "and foldCount is" + foldCount);
                if(pCount - foldCount == 1)
                {
                        System.out.println("Hand ennnnnnnnnnnnnnnded");
               
                        handOver = true;
                        return p;                      
                }
                if(currPlayerIndex < players.size()-1)
                {
                        toReturn = players.get(currPlayerIndex+1);
                        System.out.println("    " + players.get(currPlayerIndex+1).getName());
                        if(toReturn.getHasFolded())
                        {
                                System.out.println(" reeeeeeeeeeeeeeeecursion " + toReturn.getName());
                               
                                currPlayer = players.get(currPlayerIndex+1);    ////////// vincent added to fix loop (used to just send same person (one after curr
                                return (getNextPlayer(toReturn));      
                        }
                }
                else
                {
                        toReturn = players.get(0);
                        if(toReturn.getHasFolded())
                        {
                                return getNextPlayer(toReturn);
                        }
                }
                return toReturn;                
        }
        public int getPot()
        {
                return pot;
        }
        private String[] getValidActions()
        {
                String[] toReturn = new String[3];
                if(currBet == 0)
                {
                        toReturn[0] = "bet";
                        toReturn[1] = "check";
                        toReturn[2] = "fold";
                }
                else
                {
                        toReturn[0] = "raise";
                        toReturn[1] = "call";
                        toReturn[2] = "fold";
                }
                return toReturn;
        }
        private boolean handOver()
        {
                if(currRound > 3)
                        return true;
                return handOver;
        }

        public void initHand()
        {
                /////////////////////// vincent loop added to reset folders for each new hand  
                ///// the line below wiht getNextPlayer(when all the players have folded and not been resets create infinte loop
                handOver = false;       // vincent handover was never eset back to false
                int j=0;
                foldCount = 0;
                for(j = 0; players.get(j) != players.getLast(); j++){
                        players.get(j).setFolded(false);
                        players.get(j).setNotActed();
                }
                players.get(j).setFolded(false);
                players.get(j).setNotActed();
                
                myDeck.shuffleDeck();
                if(dealer == null)
                {
                        dealer = players.get(0);
                        dealer.setDealer();
                }
                currPlayer = getNextPlayer(dealer);
                
                for(int i=0; i<communityCards.size();i++)
                {
                        communityCards.remove();
                }
                dealCard();
                dealCard();    
                currRound = 0;
        }
        public void initRound()
        {
               
                handOver = false; 
                currPlayer = getNextPlayer(dealer);
                currBet = 0;
                better = currPlayer;
                for(int i=0; i<players.size(); i++)
                {
                        players.get(i).setNotActed();
                        players.get(i).calcPossibleHands(communityCards);
                }
                if(currRound == 1)
                {
                        dealFlop();
                        printFlop();
                }
                else if(currRound == 2)
                {
                        dealTurn();
                        printTurn();
                }
                else if(currRound == 3)
                {
                        dealRiver();
                        printRiver();
                }
                if(currRound == 4)
                {
                        findWinner();
                        printWinner();
                }
        }        
        private void printWinner() {
			// TODO Auto-generated method stub
			
		}


        
        public void incrementRound()
        {
                currRound++;
        }
       
        private void printDealtCard(Player currPlayer2) {
			// TODO Auto-generated method stub
        	//BoardFlop1.setImageResource(communityCards.get(5).imgId());
        	
		}        
        private void printRiver() {
			// TODO Auto-generated method stub
        	BoardFlop1.setImageResource(communityCards.get(4).imgId("full"));	
		}
		private void printTurn() {
			// TODO Auto-generated method stub
			BoardFlop1.setImageResource(communityCards.get(3).imgId("full"));
		}
		 private void printFlop() {
        	BoardFlop1.setImageResource(communityCards.get(0).imgId("full"));
        	BoardFlop2.setImageResource(communityCards.get(1).imgId("full"));
        	BoardFlop3.setImageResource(communityCards.get(2).imgId("full"));
		}


		private void findWinner()
        {
                Player winner = new Player("winner", 4);
                for(int i=0; i<players.size(); i++)
                {
                        if(winner == null)              // vincent cant say winner == null
                        {
                                if(!players.get(i).getHasFolded())
                                {
                                        winner = players.get(i);
                                }
                        }
                        else
                        {
                                if(!players.get(i).getHasFolded())
                                {
                                        if(winner.getCurrentBestHand().compareTo(players.get(i).getCurrentBestHand()) < 1)
                                        {
                                                winner = players.get(i);
                                        }
                                }
                        }
                }
        }
       
        public boolean playRound() throws IOException
        {
                String[] validActions;
                while(!roundOver())
                {
                        if(handOver == true)
                        {
                                return false;
                        }
                        validActions = getValidActions();
                        processAction(currPlayer.act(validActions, currBet));                    
                }
                if(handOver())
                {
                        return false;
                }
                return true;
        }
        private void updatePot(int pot2) {
			// TODO Auto-generated method stub        	
        	String potUpdate = String.valueOf(pot);
        	this.BoardPot.setText(potUpdate);  	
	
		}


		private void processAction(String action)
        {
                if(action == "bet") 
                        bet();
                if(action == "raise")
                        raise();
                if(action == "fold")
                        fold();
                if(action == "check")
                        check();
                if(action == "call")
                        call();
        }
		private void bet()
        {
                int cBet=0;
                cBet = currPlayer.getBet();
                addToPot( cBet );
                setCurrBet( cBet );
                currPlayer.printStatus("BET");
                better = currPlayer;                
                currPlayer = getNextPlayer(currPlayer);
        }
		private void raise()
        {
                System.out.println("RAISE!");
                currPlayer.printStatus("RAISE");
                
                int cBet=0;
                cBet = currPlayer.getBet();
                addToPot( cBet );
                setCurrBet( cBet );
                better = currPlayer;
                currPlayer = getNextPlayer(currPlayer);
        }
        private void check()
        {
        		currPlayer.printStatus("Check");
                currPlayer = getNextPlayer(currPlayer);
        }
        private void call()
        {
                System.out.println("CALL!");
                currPlayer.printStatus("CALL");
                
                int cBet=0;
                cBet = currPlayer.getBet();
                addToPot( cBet );
                setCurrBet( cBet );
                currPlayer = getNextPlayer(currPlayer);
        }
        
        public void removePlayer(Player p)
        {
                players.remove(p);
        }
        public boolean roundOver()
        {
                if(currPlayer != null && better != null)
                {
                        if(currPlayer == better && currPlayer.hasActed())
                        {
                                return true;
                        }
                        else
                        {
                                return false;
                        }
                }
                return false;
        }
        public void setCurrBet(int amt)
        {
                currBet = amt;
                
        }


		public double getNumPlayers() {
			// TODO Auto-generated method stub
			return pCount;
		}


		public LinkedList<Player> getPlayers() {
			// TODO Auto-generated method stub
			return this.players;
		}


		public LinkedList<Card> getCommCards() {
			// TODO Auto-generated method stub
			return this.communityCards;
		}


		public void clearActionLog() {
			// TODO Auto-generated method stub
			this.actionLog.clear();
			
		}


		public LinkedList<Action> getActionLog() {
			// TODO Auto-generated method stub
			return this.actionLog;
		}


		public int getCurrRound() {
			// TODO Auto-generated method stub
			return this.currRound;
		}
       
}

